#include "bezier.h"

#define round(value) ((value-(long)value)<0.5?(long)value:((long)value+1))

void initBezier(Bezier *b)
{
	b->pnode = 0;//node = null
	b->iRadius = 0;
	b->iNum = 0;
}//end constructor
//---------------------------------------------

void releaseBezier(Bezier *b)
{
	if(b->pnode != 0)
	{
		//removeAll();
	}
}//end destructor
//---------------------------------------------

/*
Input: NONE
Ouput:	1 if node == NULL
		0 if node != NULL*/
unsigned char isEmtyBezier(Bezier *b)
{
	return (b->pnode==0?1:0);
}
//---------------------------------------------

/*
Get the referent of the node at [index] position
Input: index position of the node
Ouput: the pointer to the node
*/
/*
PPoint3D CBezier::getNode(int index)
{
	if(isEmty())
		return 0;

	int i = 0;
	PPoint3D p = node;
	while((p != 0) && (i<this->iNum))
	{
		if(i == index)
		{
			return p;
		}
		p = p->next;
		i++;
	}//end while
	return 0;
}
//---------------------------------------------

void CBezier::setNode(float xx, float yy, float zz, long keyValue, int index)
{
	if(isEmty())
		return;

	int i = 0;
	PPoint3D p = node;
	while((p != 0) && (i<this->iNum))
	{
		if(i == index)
		{
			p->key = keyValue;
			p->x = xx;
			p->y = yy;
			p->z = zz;
			return;
		}
		p = p->next;
		i++;
	}//end while
}
//---------------------------------------------

	this method generate key value for each note in list
	one by one and increase 1 from the previous

long CBezier::key_generator()
{
	if(isEmty())
		return -1;
	long key = 0;
	PPoint3D p = node;

	while(p)
	{
		if(p->key == key)
		{
			key += 1;
			p = node;
		}
		else
			p = p->next;
	}
	return key;
}

//---------------------------------------------

long CBezier::getKeyValue(float xx, float yy, float zz)
{
	if(isEmty())
		return -1;
	PPoint3D p;
	p = node;
	while(p != 0)
	{
		if((p->x==xx) && (p->y==yy) && (p->z==zz))
			return p->key;
		p = p->next;
	}
	return -1;
}

//---------------------------------------------

long CBezier::isInside(float xx, float yy, float zz)
{
	//NOT DONE
	return -1;
}

int CBezier::getNumOfNode()
{
	return this->iNum;
}
//---------------------------------------------

void CBezier::addHead(PPoint3D &p)
{
	if(!isEmty())
	{
		p->next = node;
		node->before = p;
		node = p;
	}
	this->node = p;
	this->iNum++;
}
//---------------------------------------------

int CBezier::addHead(float xx, float yy, float zz, long keyValue)
{
	PPoint3D p;
	p = 0; //initialize
	p = (PPoint3D)new Point3D;

	if(p==0)
		return 0;

	p->x = xx;
	p->y = yy;
	p->z = zz;
	p->key = keyValue;
	p->before = 0; //point to NULL
	p->next = 0;	//point to NULL

	addHead(p);

	return 1;
}
//---------------------------------------------

void CBezier::addTail(PPoint3D &p)
{
	if(isEmty())
	{
		this->node = p;
	}
	else
	{
		PPoint3D temp;
		temp = node;
		while(temp->next != 0)
			temp = temp->next;

		temp->next = p;
		p->before = temp;
	}
	this->iNum++;
}
//---------------------------------------------

int CBezier::addTail(float xx, float yy, float zz, long keyValue)
{
	PPoint3D p;
	p = 0; //initialize
	p = (PPoint3D)new Point3D;

	if(p==0)	//can't locate memory for new node
		return 0;

	p->x = xx;
	p->y = yy;
	p->z = zz;
	p->key = keyValue;
	p->before = 0; //point to NULL
	p->next = 0;	//point to NULL

	addTail(p);

	return 1;
}
//---------------------------------------------

long CBezier::removeHead()
{
	if(isEmty())
		return -1;

	PPoint3D pdel;
	long result;
	pdel = this->node;
	result = pdel->key;
	if(pdel->next != 0)
	{
		node = pdel->next;
		node->before = 0;
		pdel->next = 0;
	}
	delete pdel;
	this->iNum--;
	return result;
}//end method removeHead
//---------------------------------------------


Remove the last node from the list of node
Input: NONE
Output: key value of the removed-node
long CBezier::removeTail()
{
	if(isEmty())
		return -1;

	PPoint3D pdel, ptemp;
	int result;
	pdel = node;

	while(pdel->next != 0)
		pdel = pdel->next;

	if(pdel->before != 0)
	{
		ptemp = pdel->before;
		ptemp->next = 0;
		pdel->before = 0;
	}//end if
	result = pdel->key;
	this->iNum--;
	return result;
}
//---------------------------------------------

int CBezier::removeAll()
{
	if(isEmty())
		return 0;

	int result = this->iNum;

	while(this->iNum > 0)
		removeHead();

	return result;
}
//---------------------------------------------

Point3D CBezier::generatePoint(float ft, int nn, PPoint3D &p)
{
	int i=0;

	if(nn==0)
		return p[0];

	while(nn>1)
	{
		for(i=0;i<nn-1;i++)
		{
			//p[i] = (1-ft)*p[i] + ft*p[i+1]
			p[i].x = (1-ft)*p[i].x + ft*p[i+1].x;
			p[i].y = (1-ft)*p[i].y + ft*p[i+1].y;
			//Not change z axis		
		}
		
		nn--;
	}
	return p[0];
}//end method generatePoint
//---------------------------------------------

void CBezier::draw(HDC hdc)
{
	if(isEmty())
		return;

	PPoint3D arrayNode, arrayTemp;
	PPoint3D p = this->node;
	int i = 0, n = this->iNum;
	float ft = 0.0;
	Point3D pointdraw;

	arrayNode = (PPoint3D)new Point3D[n];
	arrayTemp = (PPoint3D)new Point3D[n];

	while(i<n)
	{
		arrayNode[i].key = p->key;
		arrayNode[i].x = p->x;
		arrayNode[i].y = p->y;
		arrayNode[i].z = p->z;
		arrayNode[i].before = 0;
		arrayNode[i].next = 0;
		p = p->next;
		i++;
	}

	MoveToEx(hdc,round(arrayNode[0].x),round(arrayNode[0].y),NULL);

	while(ft<1.0)
	{
		for(i=0;i<n;i++)
			arrayTemp[i] = arrayNode[i];

		pointdraw = this->generatePoint(ft,n,arrayTemp);
		LineTo(hdc,round(pointdraw.x),round(pointdraw.y));
		ft += 0.02;
	}//end while

	delete[] arrayNode;
	delete[] arrayTemp;
}
*/
